package cn.nexd.map.location.utils;

import java.util.ArrayList;
import java.util.List;

/**
 * ObjectPool create by codingfish at 15/5/5
 * TODO:对象池。
 * 使用对象池技术有很多好处，它可以避免内存抖动，提升性能，但是在使用的时候有一些内容是需要特别注意的。
 * 通常情况下，初始化的对象池里面都是空白的，当使用某个对象的时候先去对象池查询是否存在，如果不存在则创建这个对象然后加入对象池，
 * 但是我们也可以在程序刚启动的时候就事先为对象池填充一些即将要使用到的数据，这样可以在需要使用到这些对象的时候提供更快的首次加载速度，
 * 这种行为就叫做预分配。使用对象池也有不好的一面，程序员需要手动管理这些对象的分配与释放，所以我们需要慎重地使用这项技术，避免发生对象的内存泄漏。
 * 为了确保所有的对象能够正确被释放，我们需要保证加入对象池的对象和其他外部对象没有互相引用的关系。
 *
 * @Version V1.0
 */
public class ObjectPool<T> {
    private ObjectPoolFactory<T> objectPoolFactory;
    private int maxSize;
    private List<T> freeObjects;

    public interface ObjectPoolFactory<T> {
        public T createObject();
    }

    public ObjectPool(ObjectPoolFactory<T> objectPoolFactory, int maxSize) {
        this.objectPoolFactory = objectPoolFactory;
        this.maxSize = maxSize;
        this.freeObjects = new ArrayList<T>(maxSize);
    }

    public T newObject() {
        T object = null;
        if (freeObjects.isEmpty()) {
            object = objectPoolFactory.createObject();
        } else {
            object = freeObjects.remove(freeObjects.size() - 1);
        }
        return object;
    }

    /**
     * 将对象压入对象池
     */
    public void free(T object) {
        if (freeObjects.size() < maxSize) {
            freeObjects.add(object);
        }
    }

    /**
     * 清空对象池。该操作应该在需要释放对象池资源的时候调用，否则会引起 NullPointException
     */
    public void clear() {
        if (freeObjects != null & freeObjects.size() > 0) {
            freeObjects.clear();
        }
    }
}
